/*
 * http://blog.linux.org.tw/~jserv/archives/2011/09/_mandelbrot_set.html
 * gcc -Wall -std=c99 mandelbrot.c -o mandelbrot && ./mandelbrot
 */
#include <stdio.h>
#include <stdlib.h>
#include <complex.h>

#define width_size      2050
#define height_size     1080
#define Maxval          255

static const float orig_x = width_size * 2/3;
static const float orig_y = height_size * 1/2;

typedef struct _pixel {
    unsigned char r;
    unsigned char g;
    unsigned char b;
} pixel;

static const pixel dim_gray = { 105, 105, 105 };

static unsigned char iteration(int x, int y)
{
    const int limit = Maxval + 1;
    int i;
    complex c = ((x - orig_x) / (width_size / 3)) +
    ((orig_y - y) / (height_size / 2)) * I;
    complex z = 0;

    for (i = 0; i < limit; i++) {
        /* basic formula */
        z = z * z + c;
        if (creal(z) > 2 || cimag(z) > 2)
            break;
    }
    return (unsigned char) (i == limit ? 0 : i);
}


int main()
{
    FILE *f = fopen("mandelbrot.ppm", "w+");

    /* PPM header */
    fprintf(f,
            "P6\n"      /* PPM magic number */
            "#Mandelbrot Set\n"
            "%d "       /* width, in ASCII decimal */
            "%d\n"      /* height, in ASCII decimal */
            "%d\n",     /* maximum color value, in ASCII decimal */
            width_size, height_size, Maxval);

    /* Write every pixel generated by Mandelbrot Set */
    for (int i = 0; i < height_size; i++) {
        for (int j = 0; j < width_size; j++) {
            unsigned char iter = iteration(j, i);
            if (iter) {
                pixel p = {
                    .r = iter,
                    .g = (float) abs(j - orig_x) / width_size * Maxval,
                    .b = (float) abs(i - orig_y) / height_size * Maxval };
                fwrite(&p, sizeof(pixel), 1, f);
            } else {
                fwrite(&dim_gray, sizeof(pixel), 1, f);
            }
        }
    }

    fclose(f);
    return 0;
}
